﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Xml.Linq;
using MBWebService.Core;
using System.Xml.Serialization;
using MBWebService.Core.Classes;
using MBWebService.Core.Logging;
using System.Diagnostics;

namespace MBWebService.Core
{
    public static class AppSettings
    {
        public static void Initialise()
        {
            ApplicationStartTime = DateTime.Now;
            Refresh();
            Save();
        }

        public static void Refresh()
        {
            dynamicSettings = null;
        }

        private static bool Save()
        {
            return Save(UserSettings);
        }

        public static void Restore()
        {
            if (File.Exists(FileLocation.FullName))
            {
                File.Delete(FileLocation.FullName);
            }

            Refresh();
        }

        public static bool Save(UserSettings settings)
        {
            bool retVal = SerialiseSettings(settings);
            if (retVal)
            {
                Refresh();
            }

            return retVal;
        }

        #region Constant Settings

        public static DateTime ApplicationStartTime { get; set; }

        public static FileInfo FileLocation
        {
            get
            {
                return new FileInfo(Path.Combine(AppSettings.MediaBrowserWsDirectory.FullName, @"WebServiceSettings.xml"));
            }
        }

        public static Uri Address
        {
            get
            {
                string url = string.Format(@"http://{0}:{1}/MediaBrowserService", System.Environment.MachineName, UserSettings.BasePort);
                return new Uri(url);
            }
        }

        public static Uri PublisherUri(RemoteDevice device)
        {
            return new Uri(string.Format(@"http://{0}:{1}/MbServer", device.DnsName, device.BasePort - 1));
        }

        public static Uri LocalPublisherUri
        {
            get { return PublisherUri(new RemoteDevice { DnsName = "localhost", BasePort = AppSettings.UserSettings.BasePort }); }
        }

        private static Dictionary<string, string> _mimeTypes;
        public static Dictionary<string, string> MimeTypes
        {
            get
            {
                if (_mimeTypes == null)
                {
                    _mimeTypes = new Dictionary<string, string>();
                    _mimeTypes.Add("bmp", "image/bmp");
                    _mimeTypes.Add("css", "text/css");
                    _mimeTypes.Add("gif", "image/gif");
                    _mimeTypes.Add("htm", "text/html");
                    _mimeTypes.Add("html", "text/html");
                    _mimeTypes.Add("jpeg", "image/jpeg");
                    _mimeTypes.Add("jpg", "image/jpeg");
                    _mimeTypes.Add("js", "application/x-javascript");
                    _mimeTypes.Add("manifest", "text/cache-manifest");
                    _mimeTypes.Add("png", "image/png");
                    _mimeTypes.Add("tif", "image/tiff");
                    _mimeTypes.Add("tiff", "image/tiff");
                    _mimeTypes.Add("m3u8", "application/x-mpegURL");
                    _mimeTypes.Add("ts", "video/MP2T");
                }

                return _mimeTypes;
            }
        }

        #endregion

        #region Private Methods

        private static bool SerialiseSettings(UserSettings settings)
        {
            try
            {
                XmlSerializer x = new XmlSerializer(settings.GetType());
                using (StreamWriter writer = new StreamWriter(FileLocation.FullName))
                {
                    x.Serialize(writer, settings);
                    return true;
                }
            }
            catch (Exception ex)
            {
                Logging.Logger.Instance.LogMessage("Error serialising settings: {0}", ex.Message);
                return false;
            }

        }

        private static UserSettings DeserialiseSettings()
        {
            UserSettings settings = DefaultSettings;
            if (File.Exists(FileLocation.FullName))
            {
                try
                {
                    XmlSerializer x = new XmlSerializer(typeof(UserSettings));
                    using (StreamReader reader = new StreamReader(FileLocation.FullName))
                    {
                        settings = (UserSettings)x.Deserialize(reader);
                    }
                }
                catch (Exception ex)
                {

                    // Can't have logging in here, as the settings obviously now haven't been 
                }
            }
                
            return settings;
        }

        #endregion

        #region Private Members

        private static XDocument _document;
        private static XDocument Document
        {
            get
            {
                if (_document == null)
                    _document = XDocument.Load(FileLocation.FullName);
                return _document;
            }
        }

        private static UserSettings dynamicSettings;
        
        private static UserSettings DefaultSettings
        {
            get
            {
                return new UserSettings
                {
                    BasePort = 40600,
                    Log = false,
                    RemoteComputers = new List<RemoteDevice>(),
                    ShowLoadSuccess = false,
                    FFMPEGSingleChannel = @"-ar 44100 -ac 1 -f mpegts -acodec libmp3lame -ab 64000 -s 480x320 -vcodec libx264 -b 480000 -flags +loop -cmp +chroma -partitions +parti4x4+partp8x8+partb8x8 -subq 5 -trellis 1 -refs 1 -coder 0 -me_range 16  -keyint_min 25 -sc_threshold 40 -i_qfactor 0.71 -bt 400k -maxrate 524288 -bufsize 524288 -rc_eq 'blurCplx^(1-qComp)' -qcomp 0.6 -qmin 10 -qmax 51 -qdiff 4 -level 30 -aspect 480:320 -g 30 -async 2 -",
                    FFMPEGDualChannel = @"-ar 44100 -ac 2 -f mpegts -acodec libmp3lame -ab 64000 -s 480x320 -vcodec libx264 -b 480000 -flags +loop -cmp +chroma -partitions +parti4x4+partp8x8+partb8x8 -subq 5 -trellis 1 -refs 1 -coder 0 -me_range 16  -keyint_min 25 -sc_threshold 40 -i_qfactor 0.71 -bt 400k -maxrate 524288 -bufsize 524288 -rc_eq 'blurCplx^(1-qComp)' -qcomp 0.6 -qmin 10 -qmax 51 -qdiff 4 -level 30 -aspect 480:320 -g 30 -async 2 -"
                };
            }
        }

        static DirectoryInfo ProgramDataDirectory
        {
            get
            {
                return new DirectoryInfo(Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData));
            }
        }

        #endregion

        public static UserSettings UserSettings
        {
            get
            {
                if (dynamicSettings == null)
                {
                    dynamicSettings = DefaultSettings;
                    if (File.Exists(FileLocation.FullName))
                    {
                        try
                        {
                            XmlSerializer x = new XmlSerializer(typeof(UserSettings));
                            using (StreamReader reader = new StreamReader(FileLocation.FullName))
                            {
                                dynamicSettings = (UserSettings)x.Deserialize(reader);
                            }
                        }
                        catch (Exception ex)
                        {
                            dynamicSettings.Log = true;
                            Logging.Logger.Instance.LogMessage("Error deserialising settings: {0}", ex.Message);
                            Logging.Logger.Instance.LogMessage("Using defaults...");
                            dynamicSettings.Log = false;
                        }
                    }
                }

                return dynamicSettings;
            }
        }

        public static DirectoryInfo MediaBrowserWsDirectory
        {
            get { return new DirectoryInfo(Path.Combine(ProgramDataDirectory.FullName, @"MediaBrowser\MediaBrowserWS")); }
        }

        public static DirectoryInfo WebPageBaseDirectory
        {
            get
            {
                DirectoryInfo dir = new DirectoryInfo(Path.Combine(MediaBrowserWsDirectory.FullName, "Web"));
                dir.EnsureDirectoryExistance();
                return dir;
            }
        }

        public static DirectoryInfo TrailersCacheDirectory
        {
            get
            {
                DirectoryInfo dir = new DirectoryInfo(Path.Combine(MediaBrowserWsDirectory.FullName, "TrailersCache"));
                dir.EnsureDirectoryExistance();
                return dir;
            }
        }

        public static string SessionName
        {
            get
            {
                string sessionName = System.Security.Principal.WindowsIdentity.GetCurrent().Name;
                int index = sessionName.LastIndexOf(@"\");
                if (index > 0)
                {
                    sessionName = sessionName.Substring(index + 1);
                }
                int sessionId = Process.GetCurrentProcess().SessionId;
                Logger.Instance.LogMessage("Windows Session #{0} Identity: {1}", sessionId, sessionName);

                return sessionName;
            }
        }
    }
}
